using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;

namespace FrameworkEditor
{
    public class PbUtils
    {
        private static bool isCurEnum = false;
        private static List<string> curClsName = new List<string>();

        public static void UpdatePBFromSVN()
        {
            GenPbAPI();
        }
        static void GenPbAPI()
        {
            List<string> paths = new List<string>();
            // FileUtils.FindFilesInDirectory(EditorUserSettings.GetConfigValue(PB_PROTOBUFF_FOLDER_PATH_KEY), paths,"*.proto");
            FileUtils.FindFilesInDirectory(FileUtils.PbDefinePath, paths, "*.proto");

            FileUtils.CreateDirectoryIfNotExists(FileUtils.PbEmmyLuaSavePath);

            List<string> list = new List<string>();
            List<string> finnalLines = new List<string>();

            for (var i = 0; i < paths.Count; i++)
            {
                isCurEnum = false;
                curClsName.Clear();
                list.Clear();
                finnalLines.Clear();
                //当前的proto文件
                string[] lines = File.ReadAllLines(paths[i]);
                if (IsExtractAndReformatEnum(lines))
                {
                    lines = ExtractAndReformatEnums(lines);
                }
                SplitLineList2Normal(lines, ref finnalLines);
                for (var j = 0; j < finnalLines.Count; j++)
                {
                    string finalLineStr = ExportPbToLuaStr(finnalLines[j]);
                    if (!finalLineStr.Equals(string.Empty))
                    {
                        list.Add(finalLineStr);
                    }
                }
                FileInfo info = new FileInfo(paths[i]);
                string fileName = info.Name.Replace(".proto", ".lua");
                string path = FileUtils.PbEmmyLuaSavePath + "/" + fileName;

                File.WriteAllLines(path, list.ToArray());
            }
            Debug.Log($"PB EmmyLua注释生成完成");
        }

        static void SplitLineList2Normal(string[] lineList, ref List<string> finnalLines)
        {
            string curContentTemp = String.Empty;
            Dictionary<int, List<string>> cacheLinesDic = new Dictionary<int, List<string>>();
            Dictionary<int, List<string>> finalLinesDic = new Dictionary<int, List<string>>();
            Dictionary<string, string> replaceRuleDic = new Dictionary<string, string>();
            string curClsName = string.Empty;
            int curClsIndex = 0;
            int totalClsCount = 0;
            for (int index = 0; index < lineList.Length; index++)
            {
                curContentTemp = lineList[index];
                curContentTemp = curContentTemp.Replace("\t", " ");
                if (curContentTemp.Contains("{"))
                {
                    curClsIndex = curClsIndex + 1;
                    //是否要替换内部类的名字
                    string clsName = string.Empty;
                    int msgTitleIndex = 0;
                    if (curContentTemp.IndexOf("message") >= 0)
                    {
                        msgTitleIndex = curContentTemp.IndexOf("message");
                        clsName = curContentTemp
                            .Substring(msgTitleIndex + 7, curContentTemp.IndexOf("{") - msgTitleIndex - 7).Trim();
                    }
                    else if (curContentTemp.IndexOf("enum") >= 0)
                    {
                        msgTitleIndex = curContentTemp.IndexOf("enum");
                        clsName = curContentTemp
                            .Substring(msgTitleIndex + 4, curContentTemp.IndexOf("{") - msgTitleIndex - 4).Trim();
                    }

                    if (curClsIndex == 1)
                    {
                        //缓存当前message或者enum的名字
                        curClsName = clsName;
                        replaceRuleDic.Clear();
                        cacheLinesDic.Clear();
                        finalLinesDic.Clear();
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(curClsName))
                        {
                            string nameNew = curClsName + "_" + clsName;
                            curContentTemp = curContentTemp.Replace(clsName, nameNew);
                            //缓存替换规则
                            if (replaceRuleDic.ContainsKey(clsName))
                                replaceRuleDic[clsName] = nameNew;
                            else
                                replaceRuleDic.Add(clsName, nameNew);
                            //当前类的缓存里是否有需要替换的类名
                            foreach (KeyValuePair<int, List<string>> item in cacheLinesDic)
                            {
                                for (int itemIndex = 0; itemIndex < item.Value.Count; itemIndex++)
                                {
                                    string tempValueStr = item.Value[itemIndex];
                                    string[] valueStrList = tempValueStr.Split(' ');
                                    bool isContains = false;
                                    string ruleKey = string.Empty;
                                    string ruleValue = string.Empty;
                                    foreach (KeyValuePair<string, string> itemRule in replaceRuleDic)
                                    {
                                        ruleKey = itemRule.Key;
                                        ruleValue = itemRule.Value;
                                        for (int ruleIndex = 0; ruleIndex < valueStrList.Length; ruleIndex++)
                                        {
                                            if (valueStrList[ruleIndex].CompareTo(ruleKey) == 0)
                                            {
                                                valueStrList[ruleIndex] = ruleValue;
                                                isContains = true;
                                                break;
                                            }
                                        }

                                        if (isContains)
                                            break;
                                    }

                                    //拼接回来字符串
                                    tempValueStr = string.Empty;
                                    for (int strIndex = 0; strIndex < valueStrList.Length; strIndex++)
                                    {
                                        tempValueStr += valueStrList[strIndex] + " ";
                                    }

                                    item.Value[itemIndex] = tempValueStr;
                                }
                            }

                            foreach (KeyValuePair<int, List<string>> item in finalLinesDic)
                            {
                                for (int itemIndex = 0; itemIndex < item.Value.Count; itemIndex++)
                                {
                                    string tempValueStr = item.Value[itemIndex];
                                    string[] valueStrList = tempValueStr.Split(' ');
                                    bool isContains = false;
                                    string ruleKey = string.Empty;
                                    string ruleValue = string.Empty;
                                    foreach (KeyValuePair<string, string> itemRule in replaceRuleDic)
                                    {
                                        ruleKey = itemRule.Key;
                                        ruleValue = itemRule.Value;
                                        for (int ruleIndex = 0; ruleIndex < valueStrList.Length; ruleIndex++)
                                        {
                                            if (valueStrList[ruleIndex].CompareTo(ruleKey) == 0)
                                            {
                                                valueStrList[ruleIndex] = ruleValue;
                                                isContains = true;
                                                break;
                                            }
                                        }

                                        if (isContains)
                                            break;
                                    }

                                    //拼接回来字符串
                                    tempValueStr = string.Empty;
                                    for (int strIndex = 0; strIndex < valueStrList.Length; strIndex++)
                                    {
                                        tempValueStr += valueStrList[strIndex] + " ";
                                    }

                                    item.Value[itemIndex] = tempValueStr;
                                }
                            }
                        }
                    }

                    List<string> temp = new List<string>();
                    temp.Add(curContentTemp);
                    cacheLinesDic.Add(curClsIndex, temp);
                }
                else if (curContentTemp.Contains("}"))
                {
                    cacheLinesDic[curClsIndex].Add(curContentTemp);
                    totalClsCount += 1;
                    finalLinesDic[totalClsCount] = cacheLinesDic[curClsIndex];
                    cacheLinesDic.Remove(curClsIndex);
                    curClsIndex = curClsIndex - 1;
                    if (curClsIndex == 0)
                    {
                        foreach (KeyValuePair<int, List<string>> item in finalLinesDic)
                        {
                            List<string> temp = item.Value;
                            for (int cacheIndex = 0; cacheIndex < temp.Count; cacheIndex++)
                            {
                                finnalLines.Add(temp[cacheIndex]);
                            }

                            item.Value.Clear();
                        }

                        finalLinesDic.Clear();
                        totalClsCount = 0;
                    }
                }
                else
                {
                    if (curClsIndex == 0)
                    {
                        finnalLines.Add(curContentTemp);
                    }
                    else
                    {
                        //是否要替换类名
                        string[] valueStrList = curContentTemp.Split(' ');
                        bool isContains = false;
                        string ruleKey = string.Empty;
                        string ruleValue = string.Empty;
                        foreach (KeyValuePair<string, string> itemRule in replaceRuleDic)
                        {
                            ruleKey = itemRule.Key;
                            ruleValue = itemRule.Value;
                            for (int ruleIndex = 0; ruleIndex < valueStrList.Length; ruleIndex++)
                            {
                                if (valueStrList[ruleIndex].CompareTo(ruleKey) == 0)
                                {
                                    valueStrList[ruleIndex] = ruleValue;
                                    isContains = true;
                                    break;
                                }
                            }

                            if (isContains)
                                break;
                        }

                        //拼接回来字符串
                        curContentTemp = string.Empty;
                        for (int strIndex = 0; strIndex < valueStrList.Length; strIndex++)
                        {
                            curContentTemp += valueStrList[strIndex] + " ";
                        }

                        cacheLinesDic[curClsIndex].Add(curContentTemp);
                    }
                }
            }
        }
        
        
        static bool IsExtractAndReformatEnum(string[] inputLines)
        {
            // 将所有行合并成一个字符串进行处理
            string input = string.Join("\n", inputLines);
        
            // 定义正则表达式来匹配枚举定义
            string pattern = @"message\s+\w+\s+{\s+(enum\s+\w+\s+{[^}]+})";
        
            // 使用正则表达式匹配枚举定义
            Match match = Regex.Match(input, pattern);
            return match.Success;
        }
        /// <summary>
        /// 处理message XXX {
        ///    enum YYY
        ///     {
        ///     }
        /// }情况
        /// </summary>
        /// <param name="inputLines"></param>
        /// <returns></returns>
        static string[] ExtractAndReformatEnums(string[] inputLines)
        {
            // 将所有行合并成一个字符串进行处理
            string input = string.Join("\n", inputLines);

            // Define a regex pattern to match all message blocks
            string messagePattern = @"message\s+\w+\s*{[^{}]*(?:{[^{}]*}[^{}]*)*}";
            MatchCollection messageMatches = Regex.Matches(input, messagePattern);

            // Create a list to store the output lines
            List<string> outputLines = new List<string>();

            foreach (Match messageMatch in messageMatches)
            {
                string messageBlock = messageMatch.Value;

                // Define a regex pattern to match all enum definitions
                string enumPattern = @"enum\s+\w+\s*{[^}]*}";
                MatchCollection enumMatches = Regex.Matches(messageBlock, enumPattern);

                // List to store formatted enums
                List<string> enums = new List<string>();

                foreach (Match enumMatch in enumMatches)
                {
                    // Extract and reformat each enum definition
                    string enumDefinition = enumMatch.Value;
                    enumDefinition = ReplaceFirstOccurrence(enumDefinition, "\n", " ");

                    // Add the formatted enum definition to the list
                    enums.Add(enumDefinition);

                    // Remove the enum definition from the message block content
                    messageBlock = messageBlock.Replace(enumMatch.Value, "").Trim();
                }

                // Add all formatted enums to the output
                outputLines.AddRange(enums);

                // Add the remaining message block content if it's not empty
                if (!string.IsNullOrWhiteSpace(messageBlock))
                {
                    outputLines.Add(messageBlock);
                }
            }

            // 返回处理后的行，使用 \n 分割
            return string.Join("\n", outputLines).Split(new[] { '\n' }, StringSplitOptions.None);
        }
        
        static string ReplaceFirstOccurrence(string source, string oldString, string newString)
        {
            int index = source.IndexOf(oldString);
            if (index < 0)
            {
                return source;
            }
            return source.Substring(0, index) + newString + source.Substring(index + oldString.Length);
        }

        static string ExportPbToLuaStr(string str)
        {
            if (string.IsNullOrEmpty(str))
                return string.Empty;
            if (str.Contains("import")
                || str.Contains("package com.gy.server.packet;")
                || str.Contains("option java_package")
                || str.Contains("option java_outer_classname ")
               )
            {
                return string.Empty;
            }

            if (str.Contains("{"))
            {
                if (str.Trim().IndexOf("//") == 0)
                {
                    str = str.Trim().Replace("//", "-- ");
                    return str;
                }

                //开始组建结构
                //是message还是enum
                bool isMsg = str.Contains("message");
                bool isEnum = str.Contains("enum");
                if (isMsg || isEnum)
                {
                    string curNote = String.Empty;
                    if (str.Contains("//"))
                    {
                        //截取服务器添加的注解
                        curNote = str.Substring(str.IndexOf("//") + 2);
                        str = str.Substring(0, str.IndexOf("//")); //向后截取没
                    }

                    string clsName = string.Empty;
                    int msgTitleIndex = 0;
                    if (isMsg)
                    {
                        msgTitleIndex = str.IndexOf("message");
                        clsName = str.Substring(msgTitleIndex + 7, str.IndexOf("{") - msgTitleIndex - 7).Trim();
                    }
                    else
                    {
                        msgTitleIndex = str.IndexOf("enum");
                        clsName = str.Substring(msgTitleIndex + 4, str.IndexOf("{") - msgTitleIndex - 4).Trim();
                    }

                    if (!string.IsNullOrEmpty(curNote))
                    {
                        str = "-- " + curNote + "\n" + str;
                    }

                    if (isMsg)
                    {
                        str = str.Replace("message", "---@class").Trim();
                        str = str.Replace("{", ": nil").Trim();
                        isCurEnum = false;
                    }
                    else
                    {
                        string newEnumName = clsName;
                        if (curClsName.Count > 0)
                            newEnumName = curClsName[0] + newEnumName;
                        str = "---@class " + newEnumName + " : nil\n" + newEnumName + "= {";
                        isCurEnum = true;
                    }

                    curClsName.Add(clsName);
                }
            }
            else if (str.Contains("}"))
            {
                if (str.Trim().IndexOf("//") == 0)
                {
                    str = str.Trim().Replace("//", "-- ");
                    return str;
                }

                //组建结构结束
                if (!isCurEnum)
                {
                    string nameTemp = curClsName[curClsName.Count - 1];
                    str = "local " + nameTemp + " = {}";
                }

                curClsName.RemoveAt(curClsName.Count - 1);
                if (str.Contains("//"))
                    str = str.Replace("//", "-- ").Trim();
                str += "\n";
                isCurEnum = false;
            }
            else
            {
                if (isCurEnum)
                {
                    PbEnumContent2LuaStr(ref str);
                }
                else
                {
                    PbMsgContent2LuaStr(ref str);
                }
            }

            return str;
        }

        //message内容生成注解
        static void PbMsgContent2LuaStr(ref string str)
        {
            int indexTemp = str.Trim().IndexOf("//");
            string curNote = string.Empty;
            if (indexTemp >= 0)
            {
                curNote = str.Trim().Substring(indexTemp + 2);
                if (indexTemp == 0)
                {
                    str = "-- " + curNote;
                    return;
                }
            }

            string[] arrSplit = str.Split(' ');
            int index = 0;
            int trueIndex = 0;
            bool isArr = false;
            for (var i = 0; i < arrSplit.Length; i++)
            {
                string sp = arrSplit[i];
                index = index + 1;
//                    if (sp == "\t\trequired" 
//                        || sp == "\t\toptional"
//                    )
                if (sp.Contains("required")
                    || sp.Contains("optional")
                   )
                {
                    trueIndex = index;
                    break;
                }
                else if (sp.Contains("repeated"))
                {
                    trueIndex = index;
                    isArr = true;
                    break;
                }
            }

            string fieldType = arrSplit[trueIndex];
            if (fieldType == "int32"
                || fieldType == "int64"
                || fieldType == "float"
                || fieldType == "double"
                || fieldType == "uint32"
                || fieldType == "uint64"
                || fieldType == "sint64"
                || fieldType == "fixed32"
                || fieldType == "fixed64"
                || fieldType == "sfixde32"
                || fieldType == "sfixde64"
               )
            {
                fieldType = "number";
            }
            else if (fieldType == "bool")
            {
                fieldType = "boolean";
            }
            else if (fieldType == "bytes")
            {
                fieldType = "string";
            }

            if (isArr)
            {
                fieldType += "[]";
            }

            string field = null;
            for (var i = trueIndex + 1; i < arrSplit.Length; i++)
            {
                if (arrSplit[i] != string.Empty)
                {
                    field = arrSplit[i];
                    break;
                }
            }

            if (!string.IsNullOrEmpty(field) && field != " ")
            {
                str = string.Format("---@field public {0} {1}", field, fieldType);
                if (!string.IsNullOrEmpty(curNote))
                {
                    str += "@-- " + curNote;
                }
            }
        }

        //枚举内容生成注解
        static void PbEnumContent2LuaStr(ref string str)
        {
            if (string.IsNullOrEmpty(str.Trim()))
            {
                return;
            }

            if (str.Trim().IndexOf("//") == 0)
            {
                str = str.Trim().Replace("//", "-- ");
                return;
            }

            string curEnumName = str.Substring(0, str.IndexOf("=")).Trim();
            int indexTemp = str.IndexOf("//");
            if (indexTemp > 0)
            {
                string curNote = str.Substring(indexTemp + 2);
                str = curEnumName + " = \"" + curEnumName + "\"; --" + curNote;
            }
            else if (indexTemp == 0)
            {
                str = str.Replace("//", "-- ").Trim();
            }
            else
            {
                str = curEnumName + " = \"" + curEnumName + "\";";
            }
        }
    }
}

